package com.glx.test.datafluxaispringboot.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.glx.test.datafluxaispringboot.model.ChatMessage;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;

@Service
public class StreamChatService {
    @Value("${deepseek.api.key}")
    private String apiKey;

    @Value("${deepseek.api.url}")
    private String apiUrl;

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final ChatSessionManager sessionManager;

    public StreamChatService(ChatSessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    public String createNewSessionId() {
        return "session-" + UUID.randomUUID().toString().substring(0, 8);
    }

    public void handleStreamChat(String question, String sessionId, SseEmitter emitter) throws Exception {
        // 1. 会话管理
        if (sessionId == null || sessionId.isEmpty()) {
            sessionId = createNewSessionId();
            emitter.send(SseEmitter.event().name("SESSION").data(sessionId));
        }

        // 2. 添加上下文消息
        sessionManager.addMessage(sessionId, new ChatMessage("user", question));

        // 3. 构建API请求
        String requestBody = buildRequestWithContext(sessionManager.getOrCreateSession(sessionId));

        // 4. 处理流式响应
        StringBuilder assistantResponse = new StringBuilder();
        executeApiRequest(emitter, requestBody, assistantResponse);

        // 5. 保存AI响应到上下文
        sessionManager.addMessage(sessionId, new ChatMessage("assistant", assistantResponse.toString()));
    }

    private String buildRequestWithContext(List<ChatMessage> messages) throws JsonProcessingException {
        ObjectNode requestNode = objectMapper.createObjectNode();
        ArrayNode messagesNode = requestNode.putArray("messages");

        messages.forEach(msg -> messagesNode.addObject()
                .put("role", msg.getRole())
                .put("content", msg.getContent()));

        requestNode.put("model", "deepseek-chat")
                .put("stream", true)
                .put("temperature", 0.7);

        return objectMapper.writeValueAsString(requestNode);
    }

    private void executeApiRequest(SseEmitter emitter, String requestBody, StringBuilder assistantResponse)
            throws IOException {
        try (CloseableHttpClient client = HttpClients.createDefault()) {
            HttpPost request = new HttpPost(apiUrl);
            request.setHeader("Authorization", "Bearer " + apiKey);
            request.setHeader("Content-Type", "application/json");
            request.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));

            try (CloseableHttpResponse response = client.execute(request);
                 BufferedReader reader = new BufferedReader(
                         new InputStreamReader(response.getEntity().getContent()))) {

                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.startsWith("data: ")) {
                        String jsonData = line.substring(6);
                        if ("[DONE]".equals(jsonData)) {
                            emitter.send(SseEmitter.event().data("[DONE]"));
                            break;
                        }

                        String content = parseContent(jsonData);
                        if (!content.isEmpty()) {
                            emitter.send(content);
                            assistantResponse.append(content);
                        }
                    }
                }
            }
        }
    }

    private String parseContent(String jsonData) throws JsonProcessingException {
        JsonNode root = objectMapper.readTree(jsonData);
        return root.path("choices")
                .get(0)
                .path("delta")
                .path("content")
                .asText();
    }
} 